package com.tbit.uqbike.service.business.impl;

import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbit.maintain.dto.StockMachineDTO;
import com.tbit.uqbike.constant.RecoveryLogConstant;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.business.Point;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.pojo.dto.RecoveryDownloadDTO;
import com.tbit.uqbike.object.pojo.dto.StockMachineReturnDTO;
import com.tbit.uqbike.object.pojo.vo.StockMachineVO;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.common.entity.view.PageResult;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.service.base.MachineService;
import com.tbit.uqbike.service.business.RecoveryLogService;
import com.tbit.uqbike.service.business.StockMachineService;
import com.tbit.uqbike.service.rpcservice.MachineStatusService;
import com.tbit.uqbike.webmanager.dao.core.AccountDao;
import com.tbit.uqbike.webmanager.dao.core.MachineDao;
import com.tbit.uqbike.webmanager.dao.core.StockMachineMapper;
import com.tbit.uqbike.webmanager.dao.log.RecoveryLogMapper;
import com.tbit.uqbike.webmanager.util.GeoUtil;
import com.tbit.uqbike.webmanager.util.csv.CsvExportUtils;
import com.tbit.uqbike.webmanager.util.excel.ExcelUtil;
import com.tbit.utils.DateTimeUtil;
import com.tbit.utils.DateUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author yee_
 * @version 1.0
 * @date 2023/2/20 13:36
 */
@Service
public class StockMachineServiceImpl extends ServiceImpl<StockMachineMapper, StockMachine> implements StockMachineService {

    @Resource
    private StockMachineMapper stockMachineMapper;
    @Resource
    private MachineDao machineDao;
    @Resource
    private RecoveryLogMapper recoveryLogMapper;
    @Autowired
    private MachineService machineService;
    @Autowired
    private RecoveryLogService recoveryLogService;
    @Autowired
    private CsvExportUtils csvExportUtils;
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private MachineStatusService machineStatusService;


    @Override
    public Result<PageResult<StockMachineVO>> pageList(Integer accountId, String userCode, Page<StockMachine> page) {
        Map<String, Object> queryMap = new HashMap<>(8);
        queryMap.put("accountId", accountId);
        queryMap.put("userCode", userCode);
        Integer pageCount = stockMachineMapper.pageCount(queryMap);
        if (pageCount <= 0) {
            return Result.emptyPage((int) page.getCurrent(), (int) page.getSize());
        }
        queryMap.put("start", (page.getCurrent() - 1) * page.getSize());
        queryMap.put("size", page.getSize());
        List<StockMachineVO> listResult = stockMachineMapper.pageList(queryMap);
        return Result.successPage((int) page.getCurrent(), (int) page.getSize(), pageCount, listResult);
    }

    @Override
    public Result<Double> selectMachineStockRate(Integer accountId, String userCode) {
        Map<String, Object> queryMap = new HashMap<>(8);
        queryMap.put("accountId", accountId);
        queryMap.put("userCode", userCode);
        List<Machine> machines = machineDao.selectBy(queryMap);
        if (machines.isEmpty()) {
            return Result.success(0D);
        }
        Integer stockCount = stockMachineMapper.pageCount(queryMap);
        return Result.success(Double.parseDouble(String.format("%.2f", (1.0 * stockCount / machines.size()))));
    }

    @Override
    public Result<PageResult<RecoveryLog>> recoveryList(String userCode,Integer dateState,List<Integer> accountId, String startTime, String endTime, Integer state,
                                                        Page<RecoveryLog> page) {
        LambdaQueryWrapper<RecoveryLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(RecoveryLog::getAccountId, accountId);
        if (state != null) {
            queryWrapper.eq(RecoveryLog::getState, state);
        }
        if (userCode != null) {
            queryWrapper.eq(RecoveryLog::getUserCode, userCode);
        }
        if(startTime != null && endTime != null){
            if (dateState == 0){
                queryWrapper.ge(RecoveryLog::getStartTime,startTime);
                queryWrapper.le(RecoveryLog::getStartTime, endTime);
            }else if (dateState == 1){
                queryWrapper.ge(RecoveryLog::getStockTime, startTime);
                queryWrapper.le(RecoveryLog::getStockTime, endTime);
            }else {
                queryWrapper.ge(RecoveryLog::getOutStockTime, startTime);
                queryWrapper.le(RecoveryLog::getOutStockTime, endTime);
            }
        }
        IPage<RecoveryLog> pageResult = recoveryLogMapper.selectPage(page, queryWrapper);
        List<RecoveryLog> records = pageResult.getRecords();
        if (records != null && records.size() >0){
            List<Integer> collect = records.stream().map(recoveryLog -> recoveryLog.getAccountId()).collect(Collectors.toList());
            List<Account> byAccountIds = accountDao.getByAccountIds(collect);
            Map<Integer, String> collect1 = byAccountIds.stream().collect(Collectors.toMap(Account::getAccountId, Account::getName));
            for (RecoveryLog record : records) {
                record.setAccountName(collect1.get(record.getAccountId()));
            }
        }
/*        List<Integer> warehouseIdS = records.stream().map(recoveryLog -> recoveryLog.getMachineId()).collect(Collectors.toList());
        List<StockMachineVO> stockMachineVOS = selectByMachineIdS(warehouseIdS);
        records.forEach(entity1 -> {
            // 在 list2 中查找具有相同 id 的元素
            Optional<StockMachineVO> optionalEntity2 = stockMachineVOS.stream()
                    .filter(entity2 -> entity2.getMachineId() .equals(entity1.getMachineId()) )
                    .findFirst();
            // 如果找到了对应的元素，则将 entity1 的字段值赋给它
            optionalEntity2.ifPresent(entity2 -> {
                entity1.setWarehouseId(entity2.getWarehouseId());
                entity1.setWarehouseName(entity2.getWarehouseName());
            });
        });*/
        return Result.successPage((int) page.getCurrent(), (int) pageResult.getSize(), (int) pageResult.getTotal(), records);
    }

    @Override
    public List<StockMachineVO> selectByWarehouseIdS(List<Integer> warehouseId,Integer accountId) {
        Map<String, Object> map = new HashMap<>();
        map.put("warehouseId", warehouseId);
        map.put("accountId", accountId);
        return stockMachineMapper.selectByWarehouseIdS(map);
    }

    public List<StockMachineVO> selectByMachineIdS(List<Integer> machineId) {
        Map<String, Object> map = new HashMap<>();
        map.put("machineId", machineId);
        return stockMachineMapper.selectByMachineIdS(map);
    }


    @Override
    public List<Integer> getNoWarehouseId(Integer accountId) {
        Map<String, Object> map = new HashMap<>();
        map.put("accountId", accountId);
        return stockMachineMapper.getNoWarehouseId(map);
    }

    @Override
    public List<StockMachineVO> selectByWarehouseId(Integer warehouseId) {
        Map<String, Object> map = new HashMap<>();
        map.put("warehouseId", warehouseId);
        return stockMachineMapper.selectByWarehouseId(map);
    }

    /**
     * @description: 批量出库
     * @author: mo.shanyong
     * @date: 2025/4/1 14:47
     * @param: userCodes 车辆编号
     * @param: accountId
     * @param: loginInfo
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     */
    @Override
    public Map<String, Object> delBatch(List<String> userCodes, Integer accountId, LoginInfo loginInfo) {
        List<Machine> machines = machineService.getByUserCodes(userCodes);
        Map<String, Machine> machineMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(machines)){
            machineMap = machines.stream().collect(Collectors.toMap(Machine::getUserCode, Function.identity()));
        }
        //检查车联是否能入库成功
        Map<String, Object> returnMap = this.getSuccessUserCodes(userCodes, machines, machineMap, loginInfo);
        //过滤掉不能出库的车辆
        machines = machines.stream().filter(machine -> {
            return userCodes.contains(machine.getUserCode());
        }).collect(Collectors.toList());
        List<Integer> machineIds = machines.stream().map(Machine::getMachineId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(machineIds)){
            return returnMap;
        }
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("machineId", machineIds);
        List<StockMachine> stockMachines = list(queryWrapper);
        if (!stockMachines.isEmpty()) {
            List<Integer> ids = stockMachines.stream().map(StockMachine::getBoundId).collect(Collectors.toList());
            QueryWrapper delwrapper = new QueryWrapper();
            delwrapper.in("boundId", ids);
            remove(delwrapper);
        }
        for (Machine machine : machines) {
            RecoveryLog recoveryLog = recoveryLogService.getByAccountId(machine.getAccountId(), machine.getMachineId(), RecoveryLogConstant.RECOVERYLOG_STATE_SUCCESS);
            if (Objects.nonNull(recoveryLog)) {
                recoveryLog.setState(RecoveryLogConstant.RECOVERYLOG_STATE_FALSE);
                recoveryLog.setOutStockTime(new Date());
                recoveryLog.setOutStockUserId(loginInfo.getAccountUserId());
                recoveryLog.setOutStockUserName(loginInfo.getName());
                QueryWrapper recoveryLogQueryWrapper = new QueryWrapper();
                recoveryLogQueryWrapper.eq("recoveryId", recoveryLog.getRecoveryId());
                recoveryLogMapper.update(recoveryLog, recoveryLogQueryWrapper);
            }
        }

        return returnMap;
    }

    /**
     * @description: 检查车辆编号，并返回能出库成功和不能出库的车辆
     * @author: mo.shanyong
     * @date: 2025/4/1 14:45
     * @param: userCodes 车辆编号
     * @param: machines
     * @param: machineMap
     * @param: loginInfo 登录用户
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     */
    private Map<String, Object> getSuccessUserCodes(List<String> userCodes,List<Machine> machines,Map<String, Machine> machineMap,
                                             LoginInfo loginInfo){
        //返回结果
        Map<String, Object> returnMap = new HashMap<>();
        //入库成功车辆编号
        List<StockMachineReturnDTO> successMachineList = new ArrayList<>();
        //入库失败车辆编号
        List<StockMachineReturnDTO> failMachineList = new ArrayList<>();

        List<Integer> machineIds = machines.stream().map(Machine::getMachineId).collect(Collectors.toList());
        /**获取车辆id，查询入库车辆，存在返回*/
        List<Integer> existMachineIds = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(machines)) {
           existMachineIds = stockMachineMapper.getStockMachineIdByMachineIds(machineIds);
        }
        /**找到不属于这个账户的车辆编号*/
        List<String> userNoExitUserCode = this.getUserNoExitMachineNOOrUserCode(machines,loginInfo,true);
        //可以出库的车辆编号
        List<String> successCodeList = new ArrayList<>();
        for (String userCode : userCodes) {
            Machine machine = machineMap.get(userCode);
            //车辆不存在或者车辆不属于该账户下
            if (Objects.isNull(machine) || userNoExitUserCode.contains(userCode)){
                StockMachineReturnDTO stockMachineReturnDTO = new StockMachineReturnDTO(userCode,"车辆不存在");
                failMachineList.add(stockMachineReturnDTO);
                continue;
            }
            if (!existMachineIds.contains(machine.getMachineId())){
                //已入库则不能再入库了,则是入库失败
                StockMachineReturnDTO stockMachineReturnDTO = new StockMachineReturnDTO(userCode,"车辆未入库");
                failMachineList.add(stockMachineReturnDTO);
                continue;
            }
            //记录成功
            StockMachineReturnDTO stockMachineReturnDTO = new StockMachineReturnDTO(userCode,null);
            successMachineList.add(stockMachineReturnDTO);
            successCodeList.add(userCode);
        }
        returnMap.put("successMachineList",successMachineList);
        returnMap.put("failMachineList",failMachineList);
        userCodes.clear();
        userCodes.addAll(successCodeList);
        return returnMap;
    }

    //批量修改仓库
    @Override
    public void updateBatch(List<String> userCodes,String warehouseName,String warehouseId, LoginInfo loginInfo) {
        List<Machine> machines = machineService.getByUserCodes(userCodes);
        /**批量校验*/
//        checkBatchAuth(machines, accountUser, userCodes);
        List<Integer> machineIds = machines.stream().map(Machine::getMachineId).collect(Collectors.toList());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("machineId", machineIds);
        List<StockMachine> stockMachines = list(queryWrapper);
        if (!stockMachines.isEmpty()) {
            List<Integer> ids = stockMachines.stream().map(StockMachine::getBoundId).collect(Collectors.toList());
            UpdateWrapper<StockMachine> updateWrapper = new UpdateWrapper();
            updateWrapper.in("boundId", ids);
            updateWrapper.set("warehouseName", warehouseName);
            updateWrapper.set("warehouseId", warehouseId);
            update(updateWrapper);
        }
        for (Machine machine : machines) {
            RecoveryLog recoveryLog = recoveryLogService.getByAccountId(machine.getAccountId(), machine.getMachineId(), RecoveryLogConstant.RECOVERYLOG_STATE_SUCCESS);
            if (Objects.nonNull(recoveryLog)) {
                //换库房修改库房名称和id
                recoveryLog.setStockId(Integer.valueOf(warehouseId));
                recoveryLog.setStockName(warehouseName);
                QueryWrapper recoveryLogQueryWrapper = new QueryWrapper();
                recoveryLogQueryWrapper.eq("recoveryId", recoveryLog.getRecoveryId());
                recoveryLogMapper.update(recoveryLog, recoveryLogQueryWrapper);
            }
        }
    }


    public void checkBatchAuth(List<Machine> machines, List<String> userCodes, Integer accountId) {
        List<String> existNo = new ArrayList<>();
        for (Machine machine : machines) {
            existNo.add(machine.getUserCode());
        }
        /**求差集*/
        userCodes.removeAll(existNo);
        if (!userCodes.isEmpty()) {
            throw new BaseException("车辆编号不存在");
        }
    }

    @Override
    public String recoveryListDownloadCsv(RecoveryDownloadDTO downloadDTO) {
        LambdaQueryWrapper<RecoveryLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(RecoveryLog::getAccountId, downloadDTO.getAccountId());
        String startTime = DateTimeUtil.format( downloadDTO.getStartTime(), DateUtil.YMDHMS_);
        String endTime = DateTimeUtil.format(downloadDTO.getEndTime(), DateUtil.YMDHMS_);
        if (downloadDTO.getState() != null) {
            queryWrapper.eq(RecoveryLog::getState, downloadDTO.getState());
        }
        if (downloadDTO.getUserCode() != null) {
            queryWrapper.eq(RecoveryLog::getUserCode, downloadDTO.getUserCode());
        }
        if(startTime != null && endTime != null){
            if (downloadDTO.getDateState() == 0){
                queryWrapper.ge(RecoveryLog::getStartTime,startTime);
                queryWrapper.le(RecoveryLog::getStartTime, endTime);
            }else if (downloadDTO.getDateState() == 1){
                queryWrapper.ge(RecoveryLog::getStockTime, startTime);
                queryWrapper.le(RecoveryLog::getStockTime, endTime);
            }else {
                queryWrapper.ge(RecoveryLog::getOutStockTime, startTime);
                queryWrapper.le(RecoveryLog::getOutStockTime, endTime);
            }
        }
        List<RecoveryLog> records = recoveryLogMapper.selectList(queryWrapper);
        if (records != null && records.size() >0){
            List<Integer> collect = records.stream().map(recoveryLog -> recoveryLog.getAccountId()).collect(Collectors.toList());
            List<Account> byAccountIds = accountDao.getByAccountIds(collect);
            Map<Integer, String> collect1 = byAccountIds.stream().collect(Collectors.toMap(Account::getAccountId, Account::getName));
            for (RecoveryLog record : records) {
                record.setAccountName(collect1.get(record.getAccountId()));
            }
        }
        //获取临时路径
        File tempFile = csvExportUtils.getTempFile();
        try {
            File file = csvExportUtils.exportCsv(RecoveryLog.class, tempFile, downloadDTO.getFileName(), records);
            String uploadFileName = UUID.randomUUID().toString().replace("-", "");
            //压缩上传oss
            return csvExportUtils.uploadZip(tempFile, uploadFileName, file);
        } finally {
            //删除本地文件
            FileUtil.del(tempFile);
        }
    }


    @Override
    public List<StockMachineVO> selectByWarehouseIdS(List<Integer> warehouseId,String userCode, Integer accountId) {
        Account byAccountId = accountDao.getByAccountId(accountId);
        Map<String, Object> map = new HashMap<>();
        map.put("warehouseId", warehouseId);
        map.put("accountId", accountId);
        if (null != userCode && !"".equals(userCode)){
            map.put("userCode", userCode);
            Machine byUseCode = machineDao.getByUserCode(userCode);
            if (byUseCode != null){
                map.put("machineId", byUseCode.getMachineId());
            }
        }
        List<StockMachineVO> stockMachineVOS = stockMachineMapper.selectByWarehouseIdS(map);
        List<Integer> machineIds = stockMachineVOS.stream().map(stockMachineVO -> stockMachineVO.getMachineId()).collect(Collectors.toList());
        if (machineIds != null && machineIds.size() > 0){
            List<Machine> machines = machineDao.getByMachineIdS(machineIds);
            Map<Integer, String> collect1 = machines.stream().collect(Collectors.toMap(Machine::getMachineId, Machine::getUserCode));
            List<StockMachineVO> collect = stockMachineVOS.stream().map((stockMachineVO) -> {
                if (stockMachineVO.getWarehouseName() == null || "".equals(stockMachineVO.getWarehouseName())) {
                    stockMachineVO.setWarehouseName(byAccountId.getName() + "默认仓库");
                }
                stockMachineVO.setUserCode(collect1.get(stockMachineVO.getMachineId()));
                return stockMachineVO;
            }).collect(Collectors.toList());
            return collect;
        }
        return null;
    }

    @Override
    public Result<Object> recoveryListDownload(RecoveryDownloadDTO downloadDTO) {
        LambdaQueryWrapper<RecoveryLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(RecoveryLog::getAccountId, downloadDTO.getAccountId());
        String startTime = DateTimeUtil.format( downloadDTO.getStartTime(), DateUtil.YMDHMS_);
        String endTime = DateTimeUtil.format(downloadDTO.getEndTime(), DateUtil.YMDHMS_);
        if (downloadDTO.getState() != null) {
            queryWrapper.eq(RecoveryLog::getState, downloadDTO.getState());
        }
        if (downloadDTO.getUserCode() != null) {
            queryWrapper.eq(RecoveryLog::getUserCode, downloadDTO.getUserCode());
        }
        if(startTime != null && endTime != null){
            if (downloadDTO.getDateState() == 0){
                queryWrapper.ge(RecoveryLog::getStartTime,startTime);
                queryWrapper.le(RecoveryLog::getStartTime, endTime);
            }else if (downloadDTO.getDateState() == 1){
                queryWrapper.ge(RecoveryLog::getStockTime, startTime);
                queryWrapper.le(RecoveryLog::getStockTime, endTime);
            }else {
                queryWrapper.ge(RecoveryLog::getOutStockTime, startTime);
                queryWrapper.le(RecoveryLog::getOutStockTime, endTime);
            }
        }
        List<RecoveryLog> records = recoveryLogMapper.selectList(queryWrapper);
        if (records != null && records.size() >0){
            List<Integer> collect = records.stream().map(recoveryLog -> recoveryLog.getAccountId()).collect(Collectors.toList());
            List<Account> byAccountIds = accountDao.getByAccountIds(collect);
            Map<Integer, String> collect1 = byAccountIds.stream().collect(Collectors.toMap(Account::getAccountId, Account::getName));
            for (RecoveryLog record : records) {
                record.setAccountName(collect1.get(record.getAccountId()));
            }
        }
        ExcelUtil<RecoveryLog> excelUtil = new ExcelUtil<>(RecoveryLog.class);
        JsonResult result = excelUtil.exportExcel(records, String.format("%s~%s_回收统计", cn.hutool.core.date.DateUtil.formatDate(downloadDTO.getStartTime()), cn.hutool.core.date.DateUtil.formatDate(downloadDTO.getEndTime())));
        return Result.success(result.getData());
    }

    /**
     * @description: 批量入库
     * @author: mo.shanyong
     * @date: 2025/3/31 20:00
     * @param: stockMachineDTO
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     */
    @Override
    public Map<String, Object> addBatch(StockMachineDTO stockMachineDTO,LoginInfo loginInfo) {
        /**查询回收车辆*/
        List<Machine> machines = CollectionUtils.isEmpty(stockMachineDTO.getUserCodeList()) ? machineService.getByMachineNOs(stockMachineDTO.getMachineNOList())
                : machineService.getByUserCodes(stockMachineDTO.getUserCodeList());

        Map<String, Machine> machineMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(machines)){
            machineMap = CollectionUtils.isEmpty(stockMachineDTO.getUserCodeList()) ? machines.stream().collect(Collectors.toMap(Machine::getMachineNO, Function.identity()))
                    : machines.stream().collect(Collectors.toMap(Machine::getUserCode, Function.identity()));
        }
        List<Integer> machineIds = machines.stream().map(Machine::getMachineId).collect(Collectors.toList());

        /**获取车辆id，查询入库车辆，存在返回*/
        List<Integer> existMachineIds = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(machines)) {
            existMachineIds = stockMachineMapper.getStockMachineIdByMachineIds(machineIds);
        }
        /**找到不属于这个账户的车辆编号*/
        List<String> userNoExitMachineNOOrUserCode = this.getUserNoExitMachineNOOrUserCode(machines, loginInfo,CollectionUtils.isNotEmpty(stockMachineDTO.getUserCodeList()));

        List<StockMachine> stockMachines = new ArrayList<>();
        List<RecoveryLog> recoveryLogs = new ArrayList<>();
        List<RecoveryLog> recoveryLogsInsert = new ArrayList<>();
        List<String> machineNOOrUserCodeList = CollectionUtils.isEmpty(stockMachineDTO.getUserCodeList()) ? stockMachineDTO.getMachineNOList() : stockMachineDTO.getUserCodeList();

        //检查车辆是否存在以及返回要进行业务操作的数据
        Map<String, Object> returnMap = this.getAndCheckBusinessData(stockMachines, recoveryLogs, recoveryLogsInsert, machineMap, userNoExitMachineNOOrUserCode,
                machineNOOrUserCodeList, existMachineIds, loginInfo, stockMachineDTO);

        //插入或更新数据库数据
        this.doBusiness(stockMachines,recoveryLogs,recoveryLogsInsert);
        return returnMap;
    }
    /**
     * @description: 检查车辆是否存在以及返回要进行业务操作的数据
     * @author: mo.shanyong
     * @date: 2025/4/1 9:41
     * @param: returnMap
     * @param: stockMachines
     * @param: recoveryLogs
     * @param: recoveryLogsInsert
     * @param: machineMap
     * @param: userNoExitMachineNOOrUserCode
     * @param: machineNOOrUserCodeList
     * @param: existMachineIds
     */
    private Map<String, Object> getAndCheckBusinessData(List<StockMachine> stockMachines,
                                         List<RecoveryLog> recoveryLogs,List<RecoveryLog> recoveryLogsInsert,
                                         Map<String, Machine> machineMap,List<String> userNoExitMachineNOOrUserCode,
                                         List<String> machineNOOrUserCodeList,List<Integer> existMachineIds,LoginInfo loginInfo,
                                         StockMachineDTO stockMachineDTO){
        //返回结果
        Map<String, Object> returnMap = new HashMap<>();
        //入库成功车辆编号
        List<StockMachineReturnDTO> successMachineList = new ArrayList<>();
        //入库失败车辆编号
        List<StockMachineReturnDTO> failMachineList = new ArrayList<>();
        for (String machineNOOrUserCode : machineNOOrUserCodeList) {
            Machine machine = machineMap.get(machineNOOrUserCode);
            //车辆不存在或者车辆不属于该账户下
            if (Objects.isNull(machine) || userNoExitMachineNOOrUserCode.contains(machineNOOrUserCode)){
                StockMachineReturnDTO stockMachineReturnDTO = new StockMachineReturnDTO(machineNOOrUserCode,"车辆不存在");
                failMachineList.add(stockMachineReturnDTO);
                continue;
            }
            if (existMachineIds.contains(machine.getMachineId())){
                //已入库则不能再入库了,则是入库失败
                StockMachineReturnDTO stockMachineReturnDTO = new StockMachineReturnDTO(machineNOOrUserCode,"车辆已入库");
                failMachineList.add(stockMachineReturnDTO);
                continue;
            }

            StockMachine stockMachine = new StockMachine();
            stockMachine.setAccountId(machine.getAccountId());
            stockMachine.setAddTime(new Date());
            stockMachine.setMachineId(machine.getMachineId());
            stockMachine.setUserId(loginInfo.getAccountUserId());
            stockMachine.setWarehouseName(stockMachineDTO.getWarehouseName());
            stockMachine.setWarehouseId(stockMachineDTO.getWarehouseId());
            stockMachines.add(stockMachine);
            RecoveryLog recoveryLogDB = checkRecoveryLog(machine,loginInfo);
            if (recoveryLogDB != null) {
                recoveryLogDB.setStockId(stockMachineDTO.getWarehouseId());
                recoveryLogDB.setStockName(stockMachineDTO.getWarehouseName());
                recoveryLogDB.setStockTime(new Date());
                recoveryLogs.add(recoveryLogDB);
                //如果没有回收记录,直接插入为入库
            } else {
                MachineStatus machineStatus = machineStatusService.getByMachineId(machine.getMachineId());
                if (machineStatus != null && machineStatus.getLon() != null && machineStatus.getLat() != null) {
                    recoveryLogDB = new RecoveryLog(machine.getAccountId(), machine.getMachineId(), machine.getUserCode(), machine.getMachineNO()
                            , null, machineStatus.getLon(), machineStatus.getLat(), null, "无",
                            RecoveryLogConstant.RECOVERYLOG_STATE_SUCCESS);
                    recoveryLogDB.setStockId(stockMachineDTO.getWarehouseId());
                    recoveryLogDB.setStockName(stockMachineDTO.getWarehouseName());
                    recoveryLogDB.setStockTime(new Date());
                    recoveryLogDB.setStockUserId(loginInfo.getAccountUserId());
                    recoveryLogDB.setStockUserName(loginInfo.getName());
                    recoveryLogsInsert.add(recoveryLogDB);
                }
            }
            //记录成功
            StockMachineReturnDTO stockMachineReturnDTO = new StockMachineReturnDTO(machineNOOrUserCode,null);
            successMachineList.add(stockMachineReturnDTO);
        }
        returnMap.put("successMachineList",successMachineList);
        returnMap.put("failMachineList",failMachineList);
        return returnMap;
    }

    /**
     * @description: 业务操作
     * @author: mo.shanyong
     * @date: 2025/4/1 9:32
     * @param: stockMachines
     * @param: recoveryLogs
     * @param: recoveryLogsInsert
     */
    private void doBusiness(List<StockMachine> stockMachines,List<RecoveryLog> recoveryLogs,List<RecoveryLog> recoveryLogsInsert){
        if (!stockMachines.isEmpty()) {
            this.saveBatch(stockMachines);
        }
        if (!recoveryLogs.isEmpty()) {
            recoveryLogs.stream().forEach(recoveryLog -> {
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.eq("recoveryId", recoveryLog.getRecoveryId());
                recoveryLogService.update(recoveryLog, queryWrapper);
            });
        }
        if (CollectionUtils.isEmpty(recoveryLogsInsert)){
            return;
        }
        for (RecoveryLog recoveryLog : recoveryLogsInsert) {
            recoveryLogService.save(recoveryLog);
        }
    }

    /**
     * @description: 根据账户Id(品牌、区域、加盟商id)判断车辆是否存在该账户下
     * @author: mo.shanyong
     * @date: 2025/4/1 9:13
     * @param: machineList 车辆
     * @param: loginInfo 登录用户
     * @return: java.util.List<java.lang.String>
     */
    private List<String> getUserNoExitMachineNOOrUserCode(List<Machine> machineList,LoginInfo loginInfo,boolean isUserCode){
        //如果是管理员则全部返回
        if (loginInfo.roleIsAdmin() || CollectionUtils.isEmpty(machineList)){
            return new ArrayList<>();
        }
        List<Integer> accountIdList = accountDao.getAllAccountIdByIds(new ArrayList<>(Arrays.asList(loginInfo.getId())));
        //找到不属于这个账户的车辆编号
        return machineList.stream().filter(machine -> {
            return !accountIdList.contains(machine.getAccountId());
        }).map(machine -> {
            return isUserCode ? machine.getUserCode() : machine.getMachineNO();
        }).collect(Collectors.toList());
    }


    /**
     * 回收记录校验处理
     *
     * @param machine
     * @param loginInfo
     * @return
     */
    public RecoveryLog checkRecoveryLog(Machine machine,LoginInfo loginInfo) {
        RecoveryLog recoveryLog = recoveryLogService.getByAccountId(machine.getAccountId(), machine.getMachineId(), RecoveryLogConstant.RECOVERYLOG_STATE_DEFALT);
        if (recoveryLog != null) {
            MachineStatus machineStatus = machineStatusService.getByMachineId(machine.getMachineId());
            if (machineStatus == null || machineStatus.getLon() == null || machineStatus.getLat() == null) {
                log.warn("设备位置为空" + machine.getMachineNO());
                return null;
            }
            RecoveryLog recoveryLogDB = new RecoveryLog();
            recoveryLogDB.setRecoveryId(recoveryLog.getRecoveryId());
            recoveryLogDB.setEndLo(machineStatus.getLon());
            recoveryLogDB.setEndLa(machineStatus.getLat());
//            recoveryLogDB.setEndTime(new Date());
            recoveryLogDB.setStockUserId(loginInfo.getAccountUserId());
            recoveryLogDB.setStockUserName(loginInfo.getName());
            recoveryLogDB.setState(RecoveryLogConstant.RECOVERYLOG_STATE_SUCCESS);
            recoveryLogDB.setDistance(
                    (int) GeoUtil.getDistance(new Point(recoveryLog.getStartLo(), recoveryLog.getStartLa()), new Point(recoveryLogDB.getEndLo(), recoveryLogDB.getEndLa())));
            return recoveryLogDB;
        }
        return null;
    }
}
